import hashlib
import logging
# 用于日志的记录
import pickle
from datetime import timedelta
from typing import Callable, Any, Union

import aioredis
from aioredis import ConnectionPool, Redis


from afast_core.core_libs.redis_cache.config import DEFAULT_PREFIX, DEFAULT_NAMESPACE
from afast_core.core_libs.redis_cache.redis_backend_async import AsynioRedisCache
from afast_core.core_libs.redis_cache.redis_backend_sync import SynioRedisCache
from afast_core.core_libs.redis_cache.utils import pickle_encoder, pickle_decoder, DEFAULT_NAMESPACE, DEFAULT_PREFIX,key_builder

log = logging.getLogger(__name__)
log.setLevel(logging.INFO)



class RedisCacheFactory:
    # 指向自身
    async_instance: AsynioRedisCache = None
    sync_instance: SynioRedisCache = None

    def __init__(
            self,
            *,
            host: str = "localhost",
            port: int = 6379,
            password: str = None,
            db: int = 0,
            decode_responses=True,
            # 编码和解码
            encoder: Callable[..., Any] = pickle_encoder,
            decoder: Callable[..., Any] = pickle_decoder,
            # 使用的默认的空间名DEFAULT_NAMESPACE = "main"
            namespace: str = DEFAULT_NAMESPACE,
            # 键值默认的前缀
            key_prefix: str = DEFAULT_PREFIX,
            # 键的构建方式
            key_builder: Callable[..., Any] = key_builder,
            **redis_kwargs,
    ) -> None:
        self.host = host
        self.port = port
        self.encoder = encoder
        self.decoder = decoder
        self.namespace = namespace
        self.key_prefix = key_prefix
        self.key_builder = key_builder
        self.redis_kwargs = redis_kwargs

    @classmethod
    def init(
            cls,
            password: str = None,
            db: int = 0,
            host: str = "localhost",
            port: int = 6379,
            decode_responses=True,
            encoder: Callable[..., Any] = pickle_encoder,
            decoder: Callable[..., Any] = pickle_decoder,
            namespace: str = DEFAULT_NAMESPACE,
            key_prefix: str = DEFAULT_PREFIX,
            key_builder: Callable[..., Any] = key_builder,
            cluster_mode: bool = False,
            **redis_kwargs,
    ):
        # print(parse_url(host))
        if not cls.async_instance:
            try:
                backend = AsynioRedisCache(
                    host=host,
                    port=port,
                    db=db,
                    password=password,
                    encoder=encoder,
                    decoder=decoder,
                    decode_responses=decode_responses,
                    namespace=namespace,
                    key_prefix=key_prefix,
                    key_builder=key_builder,
                    **redis_kwargs,
                )
                cls.async_instance = backend.instance
            except Exception as err:
                log.error(err)
        if not cls.sync_instance:
            try:
                backend = SynioRedisCache(
                    host=host,
                    port=port,
                    db=db,
                    password=password,
                    encoder=encoder,
                    decoder=decoder,
                    decode_responses=decode_responses,
                    namespace=namespace,
                    key_prefix=key_prefix,
                    key_builder=key_builder,
                    **redis_kwargs,
                )
                cls.sync_instance = backend.instance
            except Exception as err:
                log.error(err)

    @classmethod
    def get_async_instance(cls) -> AsynioRedisCache:
        if cls.async_instance:
            return cls.async_instance
        log.error("Redis is not intialized")

    @classmethod
    def get_sync_instance(cls) -> SynioRedisCache:
        if cls.sync_instance:
            return cls.sync_instance
        log.error("Redis is not intialized")

    @classmethod
    def close_connections(cls):
        if cls.sync_instance:
            # 关闭连接
            cls.sync_instance.close_connections()
            log.info("close redis connection")
        # 关闭异步的
        if cls.async_instance:
            from asgiref.sync import async_to_sync
            async_to_sync(cls.async_instance.close_connections)()